package com.zlp.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlp.dto.req.LoginUserReq;
import com.zlp.dto.req.UserRegisterReq;
import com.zlp.dto.resp.UserLoginResp;
import com.zlp.dto.resp.UserResp;
import com.zlp.entity.Permission;
import com.zlp.entity.User;
import com.zlp.enums.StatusEnum;
import com.zlp.enums.UserTypeEnum;
import com.zlp.exception.CustomException;
import com.zlp.mapper.UserMapper;
import com.zlp.service.UserService;
import com.zlp.utils.BeanToUtils;
import com.zlp.utils.JwtTokenUtil;
import com.zlp.utils.MethodUtil;
import com.zlp.utils.api.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 管理用户表 服务实现类
 * </p>
 *
 * @author LiPing.Zou
 * @since 2021-03-12
 */
@Service
@Slf4j(topic = "UserServiceImpl")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private UserDetailsService userDetailsService;

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Override
    public User loadUserByUsername(String username) {

        log.info("loadUserByUsername.req username={}",username);
        Wrapper<User> userWrapper = new QueryWrapper<>(new User())
                .eq("username",username);
        return this.getOne(userWrapper);
    }


    @Override
    public UserResp register(UserRegisterReq userRegisterReq) {

        log.info("register.req userRegisterReq={}", JSON.toJSONString(userRegisterReq));
        // 校验
        checkUserRegisterParam(userRegisterReq);
        User user = BeanToUtils.dtoToDo(userRegisterReq, User.class);
        user.setCreateTime(new Date());
        user.setStatus(StatusEnum.NORMAL.getValue());
        user.setUserType(UserTypeEnum.GENERAL_USER.getValue());
        //将密码进行加密操作
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        this.save(user);
        return BeanToUtils.doToDto(user, UserResp.class);
    }

    @Override
    public UserLoginResp login(LoginUserReq loginUserReq) {

        String token = null;
        try {
            UserDetails userDetails = userDetailsService.loadUserByUsername(loginUserReq.getUsername());
            if (!passwordEncoder.matches(loginUserReq.getPassword(), userDetails.getPassword())) {
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
        } catch (AuthenticationException e) {
            log.warn("登录异常:{}", e.getMessage());
        }
        return bulidUserResp(token);
    }

    @Override
    public Boolean loginOut() {

        log.info("loginOut");
        SecurityContextHolder.getContext().setAuthentication(null);
        return Boolean.TRUE;
    }

    private UserLoginResp bulidUserResp(String token) {

        UserLoginResp userLoginResp = new UserLoginResp();
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(principal instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) principal;
            userLoginResp.setUsername(userDetails.getUsername());
            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
            for (GrantedAuthority authority : authorities) {
                
            }
            
        }
        userLoginResp.setToken(token);
        userLoginResp.setTokenHead(tokenHead);
        // 设置缓存信息
        return userLoginResp;
    }


    /**
     * 校验用户注册信息
     * @param user
     * @date: 2021/3/12 21:11
     * @return: void
     */
    private void checkUserRegisterParam(UserRegisterReq user) {
        //查询是否有相同用户名的用户
        if (Objects.nonNull(loadUserByUsername(user.getUsername()))) {
            throw new CustomException(ResultCode.SYS_10004, MethodUtil.getLineInfo());
        }
    }
}
